/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_pm.h>
#include <esp_sleep.h>
#include <stdio.h>
#include <string.h>

#include <algorithm>

#include "driver/gpio.h"
#include "driver/i2c.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include "sdkconfig.h"

#include <Wire.h>

// local header
#undef LOG_TAG
#define LOG_TAG "main"
#include "ActivityMannagerServer.h"
#include "Custom_Config.h"
#include "InputEventMgr.h"
#include "LauncherActivity.h"
#include "TimerActivity.h"
#include "OledTestCase.h"
#include "DisplayCanvas.h"
#include "OscilloProbeActivity.h"
#include "PowerManager.h"
#include "SensorMgr.h"
#include "SystemServer.h"
#include "./c3log.h"
#include "fs/SpiFs.h"
#include "hal/servers/ConsoleService.h"
#include "i2c/I2cInterface.h"
#include "oled/oled_drv_intf.h"
#include "power_control/PwmCtl.h"
#include "power_track/Ina226App.h"
#include "test2.h"
#include "uart/uartintf.h"
#include <hal/servers/websocket/WebSocketService.h>


template <typename _Tp>
constexpr const _Tp& clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) {
    __glibcxx_assert(!(__hi < __lo));
    return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val;
}

#define SLEEP_SEC (1)
#define STORE_FREQ (100)
#define STRING_SIZE (256)

void printChipInfo() {
    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ", CONFIG_IDF_TARGET,
           chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);
    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
           (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
                                                         : "external");
    printf("Minimum free heap size: %d bytes\n",
           esp_get_minimum_free_heap_size());
}

void uartCB(const uint8_t* cbMsg) {
    if (cbMsg != nullptr) {
        LOGI("[main] %s", (char*)cbMsg);
    }
}

void initBaseHWDevices() {
    // update uart, 115200, 1843200, 921600
    uart_set_baudrate(UART_NUM_MAX - 1, 115200);
    uart_set_baudrate(0, 115200);

// init display devices
LOGI("init display devices start");
#if 1
    DisplayCanvas::getInstance()->init();
    DisplayCanvas::getInstance()->testWelcome();
#endif
}

void initSystemServices() {
    // init uart console
    ConsoleService consoleHandler;
    UartIntf uartIntf(&consoleHandler);
    uartIntf.start((void*)uartCB);

    // init file system
    SpiFs fs;
    fs.init();

    // init log
    init_log();

    // init System server
    SystemServer * systemServer = SystemServer::getInstance();
    // key event, can not delete
    LOGI("key event init");
    InputEventMgr * inputEventMgr = InputEventMgr::getInstance();
    inputEventMgr->init();
    inputEventMgr->registerMgr();
    systemServer->registerEventSrc(inputEventMgr);
}


void gotoLightSleep() {
#if 0
    PowerManager pwr;
    pwr.enableLightSleep();
#endif
}
extern "C" void app_main(void) {
    printf("\nI ####### main() Enter ##########\n");
    initBaseHWDevices();
    initSystemServices();

#if 1
    // create Activity
    LauncherActivity* pLauncherActivity = LauncherActivity::getInstance();
    ActivityMannagerServer::getInstance()->install(pLauncherActivity,
                                                   LauncherActivity::APPNAME);
    SystemServer::getInstance()->startActivity(pLauncherActivity);

    TimerActivity* pTimerActivity = TimerActivity::getInstance();
    ActivityMannagerServer::getInstance()->install(pTimerActivity,
                                                   TimerActivity::APPNAME);
    SystemServer::getInstance()->startSWsyncThread();
    // main loop
    LOGI("main loop");
#endif

    // no need to print, default 0
    printChipInfo();
    fflush(stdout);
    // components_func_test();
    gotoLightSleep();
    // goto sleep, must sleep, not return. return will cause stack release.
    while (true) {
        vTaskDelay(24 * 3600 * 1000 / portTICK_PERIOD_MS);
    }
}
